# 模仿静态变量的用法。

def varfunc():
    var = 0  # 每次函数调用时，都会创建一个新的局部变量var
    print('var = %d' % var)
    var += 1

"""
在这部分代码中，varfunc 是一个函数，每次调用时都会创建一个名为 var 的局部变量，并初始化为0。然后，打印 var 的值，并将其增加1。但是，由于 var 是局部变量，
当函数执行完毕后，var 的状态不会保留到下一次函数调用。所以，每次调用 varfunc 时，都会打印出 var = 0，然后 var 增加到1，但由于函数结束，这个状态不会被记住。
"""

if __name__ == '__main__':
    for i in range(3):
        varfunc()


# 类的属性
# 作为类的一个属性吧
class Static:
    StaticVar = 5

    def varfunc(self):
        self.StaticVar += 1
        print(self.StaticVar)


print(Static.StaticVar)
a = Static()
for i in range(3):
    a.varfunc()

"""
在这部分代码中，Static 是一个类，它有一个类属性 StaticVar，初始值为5。varfunc 是类的实例方法，它将 StaticVar 的值增加1，并打印出来。
类属性属于类本身，而不是类的任何特定实例。这意味着所有实例都共享这个属性。当 varfunc 被调用时，它修改的是共享的类属性 StaticVar。
"""


"""
这个例子展示了局部变量与类属性的区别：局部变量在函数调用之间不会被记住状态，而类属性在所有实例之间是共享的，修改它会影响所有实例。
"""

# 知其所以然
"""
问题： 以上函数中的var变量和类属性的StaticVar变量在内存堆栈中是如何规划的？

回答：
在Python中，内存管理是由私有的垃圾收集器处理的，它负责跟踪对象的引用计数，并在适当的时候进行回收。Python中的内存主要分为几个部分：栈（Stack）、堆（Heap）和全局/局部变量空间。

### 函数中的局部变量 `var`：

当调用函数 `varfunc()` 时，Python解释器会在栈上为该函数的调用创建一个帧（frame）。这个帧包含了函数的局部变量，包括参数、局部变量和返回地址等。局部变量 `var` 就在这个栈帧中分配。

1. **函数调用**：`varfunc()` 被调用时，一个新的栈帧被创建，`var` 被初始化为0。
2. **局部变量作用域**：`var` 只在 `varfunc()` 函数的作用域内可见。
3. **函数返回**：当 `varfunc()` 返回时，其栈帧被销毁，局部变量 `var` 被释放，不再存在于内存中。

### 类属性 `StaticVar`：

类属性 `StaticVar` 存在于类的定义中，它在内存的全局/局部变量空间中分配，而不是在栈上。这个空间是所有类实例共享的。

1. **类定义**：当类 `Static` 被定义时，类属性 `StaticVar` 被创建在全局命名空间中，所有 `Static` 类的实例都共享这个属性。
2. **属性访问和修改**：当通过实例 `a` 访问或修改 `StaticVar` 时，实际上是在全局/局部变量空间中的 `StaticVar` 被访问或修改。
3. **内存管理**：由于 `StaticVar` 是类级别的属性，它在类被定义后一直存在，直到程序结束或该类被卸载。

### 内存规划：

- **栈**：用于存储函数调用时的局部变量，如 `varfunc()` 中的 `var`。当函数执行结束，其栈帧被销毁，局部变量从栈中移除。
- **堆**：用于存储Python对象和数据结构，如类实例。类属性 `StaticVar` 也可能在堆上分配，但它是在全局/局部变量空间中进行管理的。
- **全局/局部变量空间**：用于存储类定义、全局变量和类属性等。类属性 `StaticVar` 就存储在这里。

### 总结：

局部变量 `var` 是临时存储在函数调用的栈帧中，函数调用结束后就会被销毁。而类属性 `StaticVar` 是存储在全局/局部变量空间中，所有实例都共享这个属性，它的生命周期与程序运行时的类定义相关联。
"""